原始题目:剑指 Offer 03. 数组中重复的数字 (opens new window)
# 方法一:使用集合
遍历数组,对于每个数字,先判断集合中是否有该数字,如果没有则存入集合中,如果已经存在了,那么该数字就为重复的数字。
代码:
public int findRepeatNumber(int[] nums) {
if (nums == null || nums.length == 1) {
return -1;
}
Set<Integer> set = new HashSet<>();
for (Integer n : nums) {
if (set.contains(n)) {
return n;
} else {
set.add(n);
}
}
return -1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
复杂度分析
时间复杂度:最坏的情况下,需要进行 次循环,HashSet 的添加和查找都是 的。
-空间复杂度:HashSet 占用 大小的空间。
# 方法二:原地交换
题目中说明了这个长度为 的数组中的数字的范围在 中,因此假如每个数字都是唯一的,那么必定会有 。
现在题目中说明了有数字重复了,那么我们在遍历数组的时候,遍历到数字 时,将 交换到索引 处,此时有 。那么第二次遇到数字 时,一定有 了,所以 一定是重复的数字。
算法流程:
- 遍历数组 ,初始索引位置 。
- 若 :说明 已经在对应索引位置上了,无需交换。
- 若 :说明 处和索引 处的元素值都为 ,那么 就是一个重复的数字,返回值 。
- 否则,交换索引 和 的元素值,将此数字交换至对应索引位置。
- 若遍历完尚未返回,则返回 。
代码:
复杂度分析
时间复杂度 : 需要循环 遍,每轮的判断和交换操作是 。
空间复杂度 : 使用常数级的空间。